package org.ccay.async;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ListableBeanFactory;

import org.ccay.core.exception.ApplicationException;
import org.ccay.core.log.ILogger;
import org.ccay.core.log.CcayLoggerFactory;

/**
 * 消息处理器注册中心。
 * 
 * 通过它可以获取对应消息类型的消息处理器。
 * 	
 * 
 * @since Dec 6, 2011
 */
public class MessageProcessorRegistry implements BeanFactoryAware, InitializingBean {

	/** 日志记录器 **/
	private ILogger logger = CcayLoggerFactory.getLogger(MessageProcessorRegistry.class);

	/**
	 * 哑消息处理器。
	 * 用来避免不必要的NPE.
	 * 	
	 * 
	 * @since Dec 6, 2011
	 */
	class DummyMessageProcessor implements IMessageProcessor {

		/* (non-Javadoc)
		 * @see org.ccay.core.async.MessageProcessor#process(org.ccay.core.async.Message)
		 */
		public void process(AsyncMessage message) {
			// do nothing
		}

	}

	/** 单例 **/
	private static MessageProcessorRegistry instance;

	/**
	 * 获取一个实例。
	 * 	
	 * 
	 * @since Dec 6, 2011
	 * @return
	 */
	public static MessageProcessorRegistry getInstance() {
		return instance;
	}

	/** 哑消息处理器 **/
	private IMessageProcessor dummy = new DummyMessageProcessor();
	
	/** Bean工厂 **/
	private BeanFactory beanFactory;

	/** 消息处理器注册表 **/
	private Map<String, IMessageProcessor> processors = new HashMap<String, IMessageProcessor>();

	/**
	 * 设置消息处理器
	 * 	
	 * 
	 * @since Dec 6, 2011
	 * @param processors
	 */
	public void setProcessors(Map<String, IMessageProcessor> processors) {
		if(processors != null) {
			MessageProcessorRegistry _instance = getInstance();
			Iterator<Entry<String, IMessageProcessor>> iter = processors.entrySet().iterator();
			while(iter.hasNext()) {
				Entry<String, IMessageProcessor> processor = iter.next();
				_instance.register(processor.getKey(), processor.getValue());
			}
		}
	}

	/**
	 * 获取对应消息的消息处理器。
	 * 	
	 * 
	 * @since Dec 6, 2011
	 * @param message
	 * @return
	 */
	public IMessageProcessor getProcessor(AsyncMessage message) {
		if(!this.processors.containsKey(message.getType())) {
			logger.warn("Can't find message processor for message type: "+message.getType()+
			", use dummy message processor instead!");
			return dummy;
		}

		return processors.get(message.getType());
	}

	/**
	 * 注册一个消息处理器。
	 * 	
	 * 
	 * @since Dec 6, 2011
	 * @param type
	 * @param processor
	 */
	public void register(String type, IMessageProcessor processor) {
		if(this.processors.containsKey(type)) {
			logger.warn("Duplicate message processor for message type: "+type);
		}

		processors.put(type, processor);
	}

	/** 
	 * 设置BeanFacotry.
	 * 
	 * 
	 * @since Dec 6, 2011
	 * @param beanFactory
	 * @throws BeansException
	 */
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		this.beanFactory = beanFactory;
	}

	/** 
	 * afterPropertiesSet
	 * 
	 * 
	 * @since Dec 6, 2011
	 * @throws Exception
	 */
	public void afterPropertiesSet() throws ApplicationException {
		instance = this;
		
		Map<String, IMessageProcessor> msgProcessors = ((ListableBeanFactory)this.beanFactory).getBeansOfType(IMessageProcessor.class);
		processors = msgProcessors;
	}

}
